add border width to requisition, request non-anchored children
authorHavoc Pennington <hp@redhat.com>
Tue, 13 Nov 2001 23:36:18 +0000 (23:36 +0000)
committerHavoc Pennington <hp@src.gnome.org>
Tue, 13 Nov 2001 23:36:18 +0000 (23:36 +0000)
2001-11-13  Havoc Pennington  <hp@redhat.com>

* gtk/gtktextview.c (gtk_text_view_size_request): add border width
to requisition, request non-anchored children
(gtk_text_view_size_allocate): handle border width, allocate
non-anchored children
(text_view_child_new_window): set the child as object data
(gtk_text_view_move_child): allow children at negative
coordinates, no reason why not
(gtk_text_view_forall): make it copy the list of children before
walking it, to avoid reentrancy issues
(gtk_text_view_move_child): short-circuit if position is unchanged
(changed_handler): only queue_resize if requisition has changed
(gtk_text_view_init): don't redraw_on_allocate, since we can do
a better job of invalidation ourselves

* tests/testtext.c: add tests for the fixed-position children

ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
docs/reference/gtk/tmpl/gtkmenu.sgml
gtk/gtktextview.c
tests/testtext.c

index f9b16a881eb79037971a513be88099f131f90187..d6d4973582d6388c545ebadc01c75eb660c58627 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2001-11-13  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextview.c (gtk_text_view_size_request): add border width
+       to requisition, request non-anchored children
+       (gtk_text_view_size_allocate): handle border width, allocate
+       non-anchored children
+       (text_view_child_new_window): set the child as object data
+       (gtk_text_view_move_child): allow children at negative
+       coordinates, no reason why not
+       (gtk_text_view_forall): make it copy the list of children before
+       walking it, to avoid reentrancy issues  
+       (gtk_text_view_move_child): short-circuit if position is unchanged
+       (changed_handler): only queue_resize if requisition has changed
+       (gtk_text_view_init): don't redraw_on_allocate, since we can do 
+       a better job of invalidation ourselves
+
+       * tests/testtext.c: add tests for the fixed-position children
+
 Tue Nov 13 19:51:43 2001  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkwindow.c (handle_accels_changed): protect idle handle
index f9b16a881eb79037971a513be88099f131f90187..d6d4973582d6388c545ebadc01c75eb660c58627 100644 (file)
@@ -1,3 +1,21 @@
+2001-11-13  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextview.c (gtk_text_view_size_request): add border width
+       to requisition, request non-anchored children
+       (gtk_text_view_size_allocate): handle border width, allocate
+       non-anchored children
+       (text_view_child_new_window): set the child as object data
+       (gtk_text_view_move_child): allow children at negative
+       coordinates, no reason why not
+       (gtk_text_view_forall): make it copy the list of children before
+       walking it, to avoid reentrancy issues  
+       (gtk_text_view_move_child): short-circuit if position is unchanged
+       (changed_handler): only queue_resize if requisition has changed
+       (gtk_text_view_init): don't redraw_on_allocate, since we can do 
+       a better job of invalidation ourselves
+
+       * tests/testtext.c: add tests for the fixed-position children
+
 Tue Nov 13 19:51:43 2001  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkwindow.c (handle_accels_changed): protect idle handle
index f9b16a881eb79037971a513be88099f131f90187..d6d4973582d6388c545ebadc01c75eb660c58627 100644 (file)
@@ -1,3 +1,21 @@
+2001-11-13  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextview.c (gtk_text_view_size_request): add border width
+       to requisition, request non-anchored children
+       (gtk_text_view_size_allocate): handle border width, allocate
+       non-anchored children
+       (text_view_child_new_window): set the child as object data
+       (gtk_text_view_move_child): allow children at negative
+       coordinates, no reason why not
+       (gtk_text_view_forall): make it copy the list of children before
+       walking it, to avoid reentrancy issues  
+       (gtk_text_view_move_child): short-circuit if position is unchanged
+       (changed_handler): only queue_resize if requisition has changed
+       (gtk_text_view_init): don't redraw_on_allocate, since we can do 
+       a better job of invalidation ourselves
+
+       * tests/testtext.c: add tests for the fixed-position children
+
 Tue Nov 13 19:51:43 2001  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkwindow.c (handle_accels_changed): protect idle handle
index f9b16a881eb79037971a513be88099f131f90187..d6d4973582d6388c545ebadc01c75eb660c58627 100644 (file)
@@ -1,3 +1,21 @@
+2001-11-13  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextview.c (gtk_text_view_size_request): add border width
+       to requisition, request non-anchored children
+       (gtk_text_view_size_allocate): handle border width, allocate
+       non-anchored children
+       (text_view_child_new_window): set the child as object data
+       (gtk_text_view_move_child): allow children at negative
+       coordinates, no reason why not
+       (gtk_text_view_forall): make it copy the list of children before
+       walking it, to avoid reentrancy issues  
+       (gtk_text_view_move_child): short-circuit if position is unchanged
+       (changed_handler): only queue_resize if requisition has changed
+       (gtk_text_view_init): don't redraw_on_allocate, since we can do 
+       a better job of invalidation ourselves
+
+       * tests/testtext.c: add tests for the fixed-position children
+
 Tue Nov 13 19:51:43 2001  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkwindow.c (handle_accels_changed): protect idle handle
index f9b16a881eb79037971a513be88099f131f90187..d6d4973582d6388c545ebadc01c75eb660c58627 100644 (file)
@@ -1,3 +1,21 @@
+2001-11-13  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextview.c (gtk_text_view_size_request): add border width
+       to requisition, request non-anchored children
+       (gtk_text_view_size_allocate): handle border width, allocate
+       non-anchored children
+       (text_view_child_new_window): set the child as object data
+       (gtk_text_view_move_child): allow children at negative
+       coordinates, no reason why not
+       (gtk_text_view_forall): make it copy the list of children before
+       walking it, to avoid reentrancy issues  
+       (gtk_text_view_move_child): short-circuit if position is unchanged
+       (changed_handler): only queue_resize if requisition has changed
+       (gtk_text_view_init): don't redraw_on_allocate, since we can do 
+       a better job of invalidation ourselves
+
+       * tests/testtext.c: add tests for the fixed-position children
+
 Tue Nov 13 19:51:43 2001  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkwindow.c (handle_accels_changed): protect idle handle
index f9b16a881eb79037971a513be88099f131f90187..d6d4973582d6388c545ebadc01c75eb660c58627 100644 (file)
@@ -1,3 +1,21 @@
+2001-11-13  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextview.c (gtk_text_view_size_request): add border width
+       to requisition, request non-anchored children
+       (gtk_text_view_size_allocate): handle border width, allocate
+       non-anchored children
+       (text_view_child_new_window): set the child as object data
+       (gtk_text_view_move_child): allow children at negative
+       coordinates, no reason why not
+       (gtk_text_view_forall): make it copy the list of children before
+       walking it, to avoid reentrancy issues  
+       (gtk_text_view_move_child): short-circuit if position is unchanged
+       (changed_handler): only queue_resize if requisition has changed
+       (gtk_text_view_init): don't redraw_on_allocate, since we can do 
+       a better job of invalidation ourselves
+
+       * tests/testtext.c: add tests for the fixed-position children
+
 Tue Nov 13 19:51:43 2001  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkwindow.c (handle_accels_changed): protect idle handle
index f9b16a881eb79037971a513be88099f131f90187..d6d4973582d6388c545ebadc01c75eb660c58627 100644 (file)
@@ -1,3 +1,21 @@
+2001-11-13  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextview.c (gtk_text_view_size_request): add border width
+       to requisition, request non-anchored children
+       (gtk_text_view_size_allocate): handle border width, allocate
+       non-anchored children
+       (text_view_child_new_window): set the child as object data
+       (gtk_text_view_move_child): allow children at negative
+       coordinates, no reason why not
+       (gtk_text_view_forall): make it copy the list of children before
+       walking it, to avoid reentrancy issues  
+       (gtk_text_view_move_child): short-circuit if position is unchanged
+       (changed_handler): only queue_resize if requisition has changed
+       (gtk_text_view_init): don't redraw_on_allocate, since we can do 
+       a better job of invalidation ourselves
+
+       * tests/testtext.c: add tests for the fixed-position children
+
 Tue Nov 13 19:51:43 2001  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkwindow.c (handle_accels_changed): protect idle handle
index eb37062f02d284989b271bf54174ecb0dc313070..16c0e66f96a66c4f4e7e8219581bffaa8a2091a5 100644 (file)
@@ -96,9 +96,9 @@ Creates a new #GtkMenu.
 Adds a new #GtkMenuItem to the end of the menu's item list.
 </para>
 
+<!-- # Unused Parameters # -->
 @menu: a #GtkMenu.
 @child: The #GtkMenuItem to add.
-<!-- # Unused Parameters # -->
 @m: 
 @c: 
 
@@ -108,9 +108,9 @@ Adds a new #GtkMenuItem to the end of the menu's item list.
 Adds a new #GtkMenuItem to the beginning of the menu's item list.
 </para>
 
+<!-- # Unused Parameters # -->
 @menu: a #GtkMenu.
 @child: The #GtkMenuItem to add.
-<!-- # Unused Parameters # -->
 @menu_child: 
 @m: 
 @c: 
@@ -122,10 +122,10 @@ Adds a new #GtkMenuItem to the menu's item list at the position
 indicated by @position. 
 </para>
 
+<!-- # Unused Parameters # -->
 @menu: a #GtkMenu.
 @child: The #GtkMenuItem to add.
 @pos: 
-<!-- # Unused Parameters # -->
 @position: The position in the item list where @child is added.
 Positions are numbered from 0 to n-1.
 
index 464fc50df9a59c3a9b4e34e7e4cb475eee470e3b..95834e9fae99b4759c8d811e515e4585d27fe29d 100644 (file)
@@ -978,6 +978,9 @@ gtk_text_view_init (GtkTextView *text_view)
   text_view->drag_start_y = -1;
 
   text_view->pending_place_cursor_button = 0;
+
+  /* We handle all our own redrawing */
+  gtk_widget_set_redraw_on_allocate (widget, FALSE);
 }
 
 /**
@@ -2408,6 +2411,9 @@ gtk_text_view_size_request (GtkWidget      *widget,
   if (text_view->bottom_window)
     requisition->height += text_view->bottom_window->requisition.height;
 
+  requisition->width += GTK_CONTAINER (text_view)->border_width * 2;
+  requisition->height += GTK_CONTAINER (text_view)->border_width * 2;
+  
   tmp_list = text_view->children;
   while (tmp_list != NULL)
     {
@@ -2433,7 +2439,9 @@ gtk_text_view_size_request (GtkWidget      *widget,
         }
       else
         {
-
+          GtkRequisition child_req;
+          
+          gtk_widget_size_request (child->widget, &child_req);
         }
 
       tmp_list = g_slist_next (tmp_list);
@@ -2514,7 +2522,7 @@ gtk_text_view_child_allocated (GtkTextLayout *layout,
 }
 
 static void
-gtk_text_view_validate_children (GtkTextView *text_view)
+gtk_text_view_allocate_children (GtkTextView *text_view)
 {
   GSList *tmp_list;
 
@@ -2541,7 +2549,20 @@ gtk_text_view_validate_children (GtkTextView *text_view)
         }
       else
         {
+          GtkAllocation allocation;          
+          GtkRequisition child_req;
+             
+          g_assert (child != NULL);
+          
+          allocation.x = child->x;
+          allocation.y = child->y;
 
+          gtk_widget_get_child_requisition (child->widget, &child_req);
+          
+          allocation.width = child_req.width;
+          allocation.height = child_req.height;
+          
+          gtk_widget_size_allocate (child->widget, &allocation);          
         }
 
       tmp_list = g_slist_next (tmp_list);
@@ -2565,10 +2586,15 @@ gtk_text_view_size_allocate (GtkWidget *widget,
   GdkRectangle bottom_rect;
   gint focus_edge_width;
   gboolean interior_focus;
+  gboolean size_changed;
   
   text_view = GTK_TEXT_VIEW (widget);
 
   DV(g_print(G_STRLOC"\n"));
+
+  size_changed =
+    widget->allocation.width != allocation->width ||
+    widget->allocation.height != allocation->height;
   
   widget->allocation = *allocation;
 
@@ -2590,7 +2616,7 @@ gtk_text_view_size_allocate (GtkWidget *widget,
   else
     focus_edge_width = 1;
   
-  width = allocation->width - focus_edge_width * 2;
+  width = allocation->width - focus_edge_width * 2 - GTK_CONTAINER (text_view)->border_width * 2;
 
   if (text_view->left_window)
     left_rect.width = text_view->left_window->requisition.width;
@@ -2612,7 +2638,7 @@ gtk_text_view_size_allocate (GtkWidget *widget,
   bottom_rect.width = text_rect.width;
 
 
-  height = allocation->height - focus_edge_width * 2;
+  height = allocation->height - focus_edge_width * 2 - GTK_CONTAINER (text_view)->border_width * 2;
 
   if (text_view->top_window)
     top_rect.height = text_view->top_window->requisition.height;
@@ -2634,8 +2660,8 @@ gtk_text_view_size_allocate (GtkWidget *widget,
   right_rect.height = text_rect.height;
 
   /* Origins */
-  left_rect.x = focus_edge_width;
-  top_rect.y = focus_edge_width;
+  left_rect.x = focus_edge_width + GTK_CONTAINER (text_view)->border_width;
+  top_rect.y = focus_edge_width + GTK_CONTAINER (text_view)->border_width;
 
   text_rect.x = left_rect.x + left_rect.width;
   text_rect.y = top_rect.y + top_rect.height;
@@ -2670,8 +2696,8 @@ gtk_text_view_size_allocate (GtkWidget *widget,
 
   gtk_text_view_update_layout_width (text_view);
   
-  /* This is because validating children ends up size allocating them. */
-  gtk_text_view_validate_children (text_view);
+  /* Note that this will do some layout validation */
+  gtk_text_view_allocate_children (text_view);
 
   /* Now adjust the value of the adjustment to keep the cursor at the
    * same place in the buffer
@@ -2725,6 +2751,12 @@ gtk_text_view_size_allocate (GtkWidget *widget,
       if (!gtk_text_view_flush_scroll (text_view))
         gtk_text_view_validate_onscreen (text_view);
     }
+
+  /* widget->window doesn't get auto-redrawn as the layout is computed, so has to
+   * be invalidated
+   */
+  if (size_changed && GTK_WIDGET_REALIZED (widget))
+    gdk_window_invalidate_rect (widget->window, NULL, FALSE);
 }
 
 static void
@@ -2989,7 +3021,17 @@ changed_handler (GtkTextLayout     *layout,
         }
     }
 
-  gtk_widget_queue_resize (widget);
+  {
+    GtkRequisition old_req;
+    GtkRequisition new_req;
+
+    old_req = widget->requisition;
+    gtk_widget_size_request (widget, &new_req);
+
+    if (old_req.width != new_req.width ||
+        old_req.height != new_req.height)
+      gtk_widget_queue_resize (widget);
+  }
 }
 
 static void
@@ -3841,13 +3883,15 @@ gtk_text_view_forall (GtkContainer *container,
 {
   GSList *iter;
   GtkTextView *text_view;
+  GSList *copy;
 
   g_return_if_fail (GTK_IS_TEXT_VIEW (container));
   g_return_if_fail (callback != NULL);
 
   text_view = GTK_TEXT_VIEW (container);
 
-  iter = text_view->children;
+  copy = g_slist_copy (text_view->children);
+  iter = copy;
 
   while (iter != NULL)
     {
@@ -3857,6 +3901,8 @@ gtk_text_view_forall (GtkContainer *container,
 
       iter = g_slist_next (iter);
     }
+
+  g_slist_free (copy);
 }
 
 #define CURSOR_ON_MULTIPLIER 0.66
@@ -6597,6 +6643,10 @@ text_view_child_new_window (GtkWidget          *child,
   vc->x = x;
   vc->y = y;
 
+  g_object_set_data (G_OBJECT (child),
+                     "gtk-text-view-child",
+                     vc);
+  
   return vc;
 }
 
@@ -6665,6 +6715,9 @@ gtk_text_view_add_child_at_anchor (GtkTextView          *text_view,
                                      text_view->layout);
 
   add_child (text_view, vc);
+
+  g_assert (vc->widget == child);
+  g_assert (gtk_widget_get_parent (child) == GTK_WIDGET (text_view));
 }
 
 void
@@ -6678,14 +6731,15 @@ gtk_text_view_add_child_in_window (GtkTextView          *text_view,
 
   g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
   g_return_if_fail (GTK_IS_WIDGET (child));
-  g_return_if_fail (xpos >= 0);
-  g_return_if_fail (ypos >= 0);
   g_return_if_fail (child->parent == NULL);
 
   vc = text_view_child_new_window (child, which_window,
                                    xpos, ypos);
 
   add_child (text_view, vc);
+
+  g_assert (vc->widget == child);
+  g_assert (gtk_widget_get_parent (child) == GTK_WIDGET (text_view));
 }
 
 void
@@ -6698,8 +6752,6 @@ gtk_text_view_move_child          (GtkTextView          *text_view,
 
   g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
   g_return_if_fail (GTK_IS_WIDGET (child));
-  g_return_if_fail (xpos >= 0);
-  g_return_if_fail (ypos >= 0);
   g_return_if_fail (child->parent == (GtkWidget*) text_view);
 
   vc = g_object_get_data (G_OBJECT (child),
@@ -6707,6 +6759,10 @@ gtk_text_view_move_child          (GtkTextView          *text_view,
 
   g_assert (vc != NULL);
 
+  if (vc->x == xpos &&
+      vc->y == ypos)
+    return;
+  
   vc->x = xpos;
   vc->y = ypos;
 
@@ -6715,7 +6771,6 @@ gtk_text_view_move_child          (GtkTextView          *text_view,
 }
 
 
-
 /* Iterator operations */
 
 gboolean
index ba79fafb6aabc99104c2c8caa69f761e9cdb1ed6..7f6292b47f7a82d7ea4cbced13e925ce0931f552 100644 (file)
@@ -1209,6 +1209,165 @@ do_search (gpointer callback_data,
   gtk_widget_show_all (dialog);
 }
 
+typedef struct
+{
+  /* position is in coordinate system of text_view_move_child */
+  int click_x;
+  int click_y;
+  int start_x;
+  int start_y;
+  int button;
+} ChildMoveInfo;
+
+static gboolean
+movable_child_callback (GtkWidget *child,
+                        GdkEvent  *event,
+                        gpointer   data)
+{
+  ChildMoveInfo *info;
+  GtkTextView *text_view;
+
+  text_view = GTK_TEXT_VIEW (data);
+  
+  g_return_val_if_fail (GTK_IS_EVENT_BOX (child), FALSE);
+  g_return_val_if_fail (gtk_widget_get_parent (child) == GTK_WIDGET (text_view), FALSE);  
+  
+  info = g_object_get_data (G_OBJECT (child),
+                            "testtext-move-info");
+
+  if (info == NULL)
+    {
+      info = g_new (ChildMoveInfo, 1);      
+      info->start_x = -1;
+      info->start_y = -1;
+      info->button = -1;
+      g_object_set_data_full (G_OBJECT (child),
+                              "testtext-move-info",
+                              info,
+                              g_free);
+    }
+  
+  switch (event->type)
+    {
+    case GDK_BUTTON_PRESS:
+      if (info->button < 0)
+        {
+          if (gdk_pointer_grab (event->button.window,
+                                FALSE,
+                                GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK |
+                                GDK_BUTTON_RELEASE_MASK,
+                                NULL,
+                                NULL,
+                                event->button.time) != GDK_GRAB_SUCCESS)
+            return FALSE;
+          
+          info->button = event->button.button;
+          
+          info->start_x = child->allocation.x;
+          info->start_y = child->allocation.y;
+          info->click_x = child->allocation.x + event->button.x;
+          info->click_y = child->allocation.y + event->button.y;
+        }
+      break;
+
+    case GDK_BUTTON_RELEASE:
+      if (info->button < 0)
+        return FALSE;
+
+      if (info->button == event->button.button)
+        {
+          int x, y;
+          
+          gdk_pointer_ungrab (event->button.time);
+          info->button = -1;
+
+          /* convert to window coords from event box coords */
+          x = info->start_x + (event->button.x + child->allocation.x - info->click_x);
+          y = info->start_y + (event->button.y + child->allocation.y - info->click_y);
+
+          gtk_text_view_move_child (text_view,
+                                    child,
+                                    x, y);
+        }
+      break;
+
+    case GDK_MOTION_NOTIFY:
+      {
+        int x, y;
+        
+        if (info->button < 0)
+          return FALSE;
+        
+        gdk_window_get_pointer (child->window, &x, &y, NULL); /* ensure more events */
+
+        /* to window coords from event box coords */
+        x += child->allocation.x;
+        y += child->allocation.y;
+        
+        x = info->start_x + (x - info->click_x);
+        y = info->start_y + (y - info->click_y);
+        
+        gtk_text_view_move_child (text_view,
+                                  child,
+                                  x, y);
+      }
+      break;
+
+    default:
+      break;
+    }
+
+  return FALSE;
+}
+
+static void
+add_movable_child (GtkTextView      *text_view,
+                   GtkTextWindowType window)
+{
+  GtkWidget *event_box;
+  GtkWidget *label;
+  GdkColor color;
+  
+  label = gtk_label_new ("Drag me around");  
+  
+  event_box = gtk_event_box_new ();
+  gtk_widget_add_events (event_box,
+                         GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+                         GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
+
+  color.red = 0xffff;
+  color.green = color.blue = 0;
+  gtk_widget_modify_bg (event_box, GTK_STATE_NORMAL, &color);
+  
+  gtk_container_add (GTK_CONTAINER (event_box), label);
+
+  gtk_widget_show_all (event_box);
+
+  g_signal_connect (G_OBJECT (event_box), "event",
+                    G_CALLBACK (movable_child_callback),
+                    text_view);
+
+  gtk_text_view_add_child_in_window (text_view,
+                                     event_box,
+                                     window,
+                                     0, 0);
+}
+
+static void
+do_add_children (gpointer callback_data,
+                 guint callback_action,
+                 GtkWidget *widget)
+{
+  View *view = view_from_widget (widget);
+
+  add_movable_child (GTK_TEXT_VIEW (view->text_view),
+                     GTK_TEXT_WINDOW_WIDGET);
+  add_movable_child (GTK_TEXT_VIEW (view->text_view),
+                     GTK_TEXT_WINDOW_LEFT);
+  add_movable_child (GTK_TEXT_VIEW (view->text_view),
+                     GTK_TEXT_WINDOW_RIGHT);
+}
+
 static void
 view_init_menus (View *view)
 {
@@ -1301,6 +1460,7 @@ static GtkItemFactoryEntry menu_items[] =
   { "/_Test",           NULL,         0,           0, "<Branch>" },
   { "/Test/_Example",           NULL,         do_example,  0, NULL },
   { "/Test/_Insert and scroll", NULL,         do_insert_and_scroll,  0, NULL },
+  { "/Test/_Add fixed children", NULL,         do_add_children,  0, NULL },
 };
 
 static gboolean